﻿using System;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Threading;
using System.Windows;
using System.Windows.Input;
using GBL.Repository.Resources;
using GBlason.Common;
using GBlason.Common.CustomCommand;
using GBlason.Control.DialogBox;
using GBlason.Global;
using GBlason.Properties;
using GBlason.ViewModel;
using GBlason.ViewModel.Contract;
using GBlason.ViewModel.Control;
using GBlason.ViewModel.General;
using GBlasonLogic.Rules;
using Microsoft.Win32;

namespace GBlason
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow
    {
        /// <summary>
        /// Application Entry Point.
        /// </summary>
        [STAThreadAttribute]
        [DebuggerNonUserCodeAttribute]
        public static void Main()
        {
            bool onlyInstance;
            var mutex = new Mutex(true, "UniqueGBlasonInstance", out onlyInstance);
            if (!onlyInstance)
            {
                return;
            }
            var app = new App();
            app.InitializeComponent();
            app.Run();
            GC.KeepAlive(mutex);
        }

        public MainWindow()
        {
            ApplicationStarter();
            Closing += MainWindow_Closing;
        }

        void MainWindow_Closing(object sender, CancelEventArgs e)
        {
            //sauvegarde des settings
            var tamponFile = new StringCollection();
            ApplicationSettingsManager.SaveCollectionSettings(ref tamponFile, GlobalApplicationViewModel.GetApplicationViewModel.RecentFiles);
            Settings.Default.RecentFiles = tamponFile;
            var tamponDir = new StringCollection();
            ApplicationSettingsManager.SaveCollectionSettings(ref tamponDir, GlobalApplicationViewModel.GetApplicationViewModel.RecentDirectories);
            Settings.Default.RecentDirectories = tamponDir;
            ApplicationSettingsManager.SavePreference();
            Settings.Default.Save();
        }

        #region static unique pages (home and resource)

        private ResourceEditorViewModel _uniqueResourcePage;

        private StartingPageViewModel _uniqueStartingPage;

        #endregion

        /// <summary>
        /// Steps to start properly the application
        /// </summary>
        private void ApplicationStarter()
        {
            //chargement des settings
            GlobalApplicationViewModel.GetApplicationViewModel.RecentFiles.Clear();
            try
            {
                GlobalApplicationViewModel.GetApplicationViewModel.AddRecentFilesCollection(ApplicationSettingsManager.LoadCollectionSettings<RecentFileViewModel>(Settings.Default.RecentFiles));
                GlobalApplicationViewModel.GetApplicationViewModel.AddRecentDirectoriesCollection(ApplicationSettingsManager.LoadCollectionSettings<RecentFileViewModel>(Settings.Default.RecentDirectories));

                ApplicationSettingsManager.LoadPreferences();
            }
            catch (InvalidOperationException ioe)
            {
                new ExceptionDialogBox(new CustomException(Properties.Resources.ExceptionLoadingPreferences, ioe) { Importance = ExceptionImportance.NoImpact }).ShowDialog();
                Settings.Default.RecentFiles.Clear();
                Settings.Default.RecentDirectories.Clear();
            }
            Settings.Default.Save();

            //initialisation des objets
            try
            {
                GbrFileViewModel.GetResources.InitFromFile();
            }
            catch (NullReferenceException nex)
            {
                new ExceptionDialogBox(new CustomException(Properties.Resources.ExceptionLoadingResourceVersion, nex) { Importance = ExceptionImportance.NoImpact }).ShowDialog();
                Settings.Default.RecentFiles.Clear();
                Settings.Default.RecentDirectories.Clear();
            }

            //Initialisation des ecrans statique (page d'accueil) aussi sauvegarde dans les parametres
            _uniqueStartingPage = new StartingPageViewModel();
            GlobalApplicationViewModel.GetApplicationViewModel.OpenedFiles.Add(_uniqueStartingPage);
        }

        #region events
        private void RecentObjectSelected(object sender, ExecutedRoutedEventArgs e)
        {
            var recentFile = e.Parameter as RecentFileViewModel;
            if (recentFile == null)
            {
                MessageBox.Show("Erreur lors du chargement des objets resource ", "Erreur", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }
            var path = recentFile.Path;
            if (!File.Exists(path))
            {
                //it should be a directory
                if (Directory.Exists(path))
                {
                    OpenCommandExecuted(this, e);
                }
                return;
            }
            GbsFileViewModel.OpenFiles(new[] { path });
            TabHome.IsSelected = true;
        }


        private void OpenCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private void OpenCommandExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            var dirSelected = e.Parameter as RecentFileViewModel;

            var dialogOpener = new OpenFileDialog
            {
                DefaultExt = String.Format(CultureInfo.CurrentCulture,
                                           ".{0}",
                                           Properties.Resources.GBSFormatExtension),
                Filter = String.Format(CultureInfo.CurrentCulture,
                                       "{0} (.{1})|*.{1}",
                                       Properties.Resources.OpenDialogBoxFormatDescription,
                                       Properties.Resources.GBSFormatExtension),
                Multiselect = true
            };
            if (dirSelected != null)
                dialogOpener.InitialDirectory = dirSelected.Path;
            try
            {
                var result = dialogOpener.ShowDialog();
                if (result.Value)
                {
                    GbsFileViewModel.OpenFiles(dialogOpener.FileNames);
                    TabHome.IsSelected = true;
                }

            }
            catch (FileNotFoundException fex)
            {
                new ExceptionDialogBox(new CustomException(Properties.Resources.ExceptionFileNotFoundMessage, fex) { Importance = ExceptionImportance.NoImpact }).ShowDialog();
            }
            catch (InvalidOperationException ioex)
            {
                new ExceptionDialogBox(new CustomException(Properties.Resources.ExceptionFormatReadingError, ioex) { Importance = ExceptionImportance.NoImpact }).ShowDialog();
            }
        }

        private void NewCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private void NewCommandExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            var newCoatOfArmsFile = GbsFileViewModel.CreateNew(GlobalApplicationViewModel.GetNewFileName());
            GlobalApplicationViewModel.GetApplicationViewModel.OpenedFiles.Add(newCoatOfArmsFile);
            GlobalApplicationViewModel.GetApplicationViewModel.CurrentlyDisplayedFile = newCoatOfArmsFile;
            TabHome.IsSelected = true;
        }

        private void SaveCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = false;
            //the difference with the save as is when the issavable file will be put on, save won't be allowed then
            if (GlobalApplicationViewModel.GetApplicationViewModel.CurrentlyDisplayedFile != null)
                e.CanExecute = true;
        }

        private void SaveCommandExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            if (!String.IsNullOrEmpty(GlobalApplicationViewModel.GetApplicationViewModel.CurrentlyDisplayedFile.FullFileName))
                GlobalApplicationViewModel.GetApplicationViewModel.CurrentlyDisplayedFile.SaveThisFile(
                    GlobalApplicationViewModel.GetApplicationViewModel.CurrentlyDisplayedFile.FullFileName);
            else
                SaveAsCommandExecuted(sender, e);
        }

        private void SaveAsCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = false;
            if (GlobalApplicationViewModel.GetApplicationViewModel.CurrentlyDisplayedFile != null)
                e.CanExecute = true;
        }

        private void SaveAsCommandExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            var saveFileDialog = new SaveFileDialog
            {
                DefaultExt = String.Format(CultureInfo.CurrentCulture,
                                           ".{0}",
                                           Properties.Resources.GBSFormatExtension),
                Filter = String.Format(CultureInfo.CurrentCulture,
                                       "{0} (.{1})|*.{1}",
                                       Properties.Resources.OpenDialogBoxFormatDescription,
                                       Properties.Resources.GBSFormatExtension),
                FileName = GlobalApplicationViewModel.GetApplicationViewModel.CurrentlyDisplayedFile.FileName,
                AddExtension = true
            };
            if (saveFileDialog.ShowDialog() == true)
                GlobalApplicationViewModel.GetApplicationViewModel.CurrentlyDisplayedFile.SaveThisFile(
                    saveFileDialog.FileName);
        }

        private void AddDivisionCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            var command = e.Command as AddDivisionCommand;
            e.CanExecute = false;
            if (command == null || GlobalApplicationViewModel.GetApplicationViewModel.CurrentlyDisplayedFile == null ||
                GlobalApplicationViewModel.GetApplicationViewModel.CurrentlyDisplayedFile.CurrentlySelectedComponent ==
                null) return;
            var currentObject =
                GlobalApplicationViewModel.GetApplicationViewModel.CurrentlyDisplayedFile.CurrentlySelectedComponent
                as IDivisible;
            //we need to know which kind of division have to be added here
            if (currentObject == null || !(e.Parameter is DivisionType)) return;

            e.CanExecute = DivisionRules.IsAllowed(currentObject.GetDivisionsConstraints(), (DivisionType)e.Parameter);
        }

        private void AddDivisionCommandExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            var command = e.Command as AddDivisionCommand;
            if (command != null)
                command.Do(new CommandParameter(
                    e.Parameter,
                    GlobalApplicationViewModel.GetApplicationViewModel.CurrentlyDisplayedFile,
                    GlobalApplicationViewModel.GetApplicationViewModel.CurrentlyDisplayedFile.CurrentlySelectedComponent as ICommandTarget));
        }

        private void DeleteResourceCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {

        }

        private void DeleteResourceCommandExecuted(object sender, ExecutedRoutedEventArgs e)
        {

        }

        private void ViewResourceCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private void ViewResourceCommandExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            if (_uniqueResourcePage == null)
            {
                _uniqueResourcePage = new ResourceEditorViewModel();
                GlobalApplicationViewModel.GetApplicationViewModel.OpenedFiles.Add(_uniqueResourcePage);
            }
            else
            {
                //visibility management
            }
            GlobalApplicationViewModel.GetApplicationViewModel.CurrentlyDisplayedFile = _uniqueResourcePage;
        }

        private void AddResourceCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {

        }

        private void AddResourceCommandExecuted(object sender, ExecutedRoutedEventArgs e)
        {

        }

        private void EditResourceCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {

        }

        private void EditResourceCommandExecuted(object sender, ExecutedRoutedEventArgs e)
        {

        }
        #endregion
    }
}
